require 'messages'
require 'networking'
require 'threads'

local messenger = nil

local function create_messages()
    
    local messenger = Messenger:create()
    
    messenger:registerGroup(messages,        "player")
    messenger:registerGroup(messages.player, "movement")

    local playerJump = {
        name  = "jump",
        force = 10
    }

    local playerMove = {
        name  = "move",
        angle = 0 -- straight ahead
    }

    local playerStopMove = {
        name = "stopmove"
    }

    local playerFire = {
        name = "fire",
        mode = 0 -- weapon mode
    }
    
    local test = {
        name = "test",
        field = "What hath God wrought" -- lolz morse
    }

    messenger:registerMessage(messages.player.movement, playerJump)
    messenger:registerMessage(messages.player.movement, playerMove)
    messenger:registerMessage(messages.player.movement, playerStopMove)
    messenger:registerMessage(messages.player,          playerFire)
    
    messenger:registerMessage(messages, test)
    
    -- Test our hierarchy was properly made
    assert(messages.player.movement.jump.force == 10)
    
    return true
end

local function setup_network()
    messageScheduler = Scheduler:create()
    
    -- create the objects
    server = Server:create()
    client1 = Client:create()
    client2 = Client:create()
    monitor = Tasklet:create()
    
    serverMessenger = Messenger:create()
    client1Messenger = Messenger:create()
    client2Messenger = Messenger:create()
    
    serverMessenger:setNetworkInterface(server)
    client1Messenger:setNetworkInterface(client1)
    client2Messenger:setNetworkInterface(client2)
    
    -- set up the network
    server:bind("*", 1234)
    server:startListening()
    
    client1:connect("127.0.0.1", 1234)
    client2:connect("127.0.0.1", 1234)
    
    messageScheduler:addTask(server)
    messageScheduler:addTask(client1)
    messageScheduler:addTask(client2)
    
    -- wait until all clients are connected
    
    monitor.main = 
        function()
            while (client1.connected == false and client2.connected == false) do
                yield()
            end
            messageScheduler:stop()
        end
    
    messageScheduler:addTask(monitor)
    messageScheduler:start()
    
    return true
    
end

function send_messages()
    local client1Driver = Tasklet:create()
    local client2Driver = Tasklet:create()
    
    function client1Driver:main()
        while (true) do
            self:sleep(0.75)
            client1Messenger:send(messages.test)
        end
    end
    
    function client2Driver:main()
        self:sleep(1.5)
        client2Messenger:send(messages.player.movement.jump)
        self:sleep(0.5)
        client2Messenger:send(messages.player.fire)
        self:sleep(0.1)
        client2Messenger:send(messages.player.fire)
        self:sleep(4)
        client2:disconnect()
    end
    
    function monitor:main()
        self:sleep(5)
        serverMessenger:send(messages.player.fire)
        self:sleep(5)
        messageScheduler:stop()
    end
    
    messageScheduler:addTask(monitor)
    messageScheduler:addTask(client1Driver)
    messageScheduler:addTask(client2Driver)
    
    messageScheduler:start()
    
    return true
    
end

if tests == nil then tests = {} end

tests.messages = {
    create_messages = {
        description = "Creates a collection of messages",
        test = create_messages,
        prerequisites = {}
    },    
    
    setup_network = {
        description = "Sets up a network system of 1 server and 2 clients",
        test = setup_network,
        prerequisites = {"create_messages"}
    },
    
    send_messages = {
        description = "Sends a bunch of messages to and from clients for 10 seconds",
        test = send_messages,
        prerequisites = {"setup_network"}
    }
}
